Re: Recent troubles

Darren Reed (avalon@coombs.anu.edu.au)
Wed, 25 Jan 1995 14:56:36 +1100 (EDT)

> 
> Someone replied to my
> 
> >> If I had source, I'd probably corrupt tcp_iss on not only received
> >> packets but also [...].
> 
> with
> 
> > You should read RFC 793 (if you haven't).
> 
> This was all; there was no indication _what_ in RFC793 was felt
> relevant.  (RFC793 is the TCP spec.)

I did, but not to the list.  But anyway...

> I assume the section being talked about is the following part of 3.3;
> this is a serious enough point that I think it's worth sending this to
> the whole list, especially since I didn't mention this with the code I
> posted.
> 
> +----------------
> | Initial Sequence Number Selection
> |
> | The protocol places no restriction on a particular connection being
> | used over and over again.  A connection is defined by a pair of
> | sockets.  New instances of a connection will be referred to as
> | incarnations of the connection.  The problem that arises from this is
> | -- "how does the TCP identify duplicate segments from previous
> | incarnations of the connection?"  This problem becomes apparent if
> | the connection is being opened and closed in quick succession, or if
> | the connection breaks with loss of memory and is then reestablished.
> |
> | To avoid confusion we must prevent segments from one incarnation of a
> | connection from being used while the same sequence numbers may still
> | be present in the network from an earlier incarnation.  We want to
> | assure this, even if a TCP crashes and loses all knowledge of the
> | sequence numbers it has been using.  When new connections are
> | created, an initial sequence number (ISN) generator is employed which
> | selects a new 32 bit ISN.  The generator is bound to a (possibly
> | fictitious) 32 bit clock whose low order bit is incremented roughly
> | every 4 microseconds.  Thus, the ISN cycles approximately every 4.55
> | hours.  Since we assume that segments will stay in the network no
> | more than the Maximum Segment Lifetime (MSL) and that the MSL is less
> | than 4.55 hours we can reasonably assume that ISN's will be unique.
> +----------------
> 
> Yes, the tactic I described (and implemented) for generating
> harder-to-guess ISNs violates this spec.  Like any method that
> generates "random" ISNs, it runs the risk that old segments may be
> mistaken for data on newly-established connections.
> 
> Several factors combine to make me ignore this risk.
> 
> First is that, assuming the method does generate reasonably random
> ISNs, it's unlikely.  For a 4K maximum window size, it would require a
> one-in-a-million coincidence (4G/4K), and even then it would have to
> hit all the unlikely items below.  (For fat-pipe TCP, the chance is
> higher; for a half-meg window, for example, it's more like one in
> 8192.)

how quickly can you send 1MB of data from host to host ?
10 seconds (best) ?

> Third is that the new connection must use exactly the same port numbers
> as the old.  Unless the other end of the connection crashes too, this
> is extremely unlikely because it will have a TIME_WAIT socket sitting
> around preventing this.

What about SO_REUSEADDR or do you disable this in all programs you
compile ? (A lot enable it to stop TIME_WAIT connections building up in
the kernel).

> Fourth is the quiet time on TCP reboot, specifically for old segments
> to run out of TTL.  If and when machines reboot fast enough for this to
> be a problem, their TCPs need to be taught about this anyway, and that
> should take care of it.

eh ? TTL rarely works as you say...nearly always a hop count thing.

> Thus, I'll take the resistance to known attacks over the small risk
> that two simultaneous host crashes, a very peculiar routing glitch,
> extremely accelerated reboots, and a fluke somewhere between one in
> 8192 and one in 2^20 all conflue to corrupt a connection.
> 
> You may choose differently.  You're welcome to.
> 
> Unless of course you can suggest some better solution, something I can
> implement in (say) less than 48 hours (my defense was done the same
> afternoon I did the defense against LKMs and /dev/*mem).  I agree that
> TCP needs to be redesigned...but that's not much help when machines are
> being attacked _today_.  I'll be glad to talk redesign, once I have
> some insulation against existing crackers.

Oh, I thought it was obvious, just ensure that the seq# changes more
often than it does and with some (large) uncertainty.  Although you have
a nice CRC algorithm there, it (a) doesn't appear to handle the case
where tcp_iss should wrap (TCP_COMPAT_42) (b) can be calculated.  Every
so often, despite your attempts, it will go back to 0 (tcp_iss) and from
there you can do the math yourself.  So the game becomes to get a packet
to be the first in after tcp_iss goes back to 0...the crackers have your
code, they can do the math themselves.

Surely there is a timing routing in the kernel somewhere which you could
plug a bit of extra assembly in...